import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;


public class WeightedDirectedGraph<ItemType, CostType> {
	private Map<ItemType, Vertex> vertices;
	
	public WeightedDirectedGraph() {
		vertices = new LinkedHashMap<ItemType, Vertex>();
	}
	
	public void addItem(ItemType item) {
		vertices.put(item, new Vertex(item));
	}
	
	public void addEdge(ItemType from, ItemType to, CostType cost) {
		Vertex vertex = vertices.get(from);
		if(vertex != null) {
			vertex.addZijde(vertices.get(to), cost);
		}
	}
	
	public ArrayList<ItemType> getNeighbours(ItemType item) {
		ArrayList<ItemType> returnTypes = new ArrayList<ItemType>();
		Vertex vertex = vertices.get(item);
		if(vertex != null) {
			for(Vertex v : vertex.getBuurKnopen()) {
				returnTypes.add(v.getItem());
			}
		}
		return returnTypes;
	}
	
	public CostType getCost(ItemType from, ItemType to) {
		Vertex vertex = vertices.get(from);
		if(vertex != null) {
			return vertex.getCost(vertices.get(to));
		}
		return null;
	}
	
	public int size() {
		return vertices.size();
	}
	
	//////////RESET FUNCTION/////////
	public void maakAllesWeerNietBezocht(Vertex start) {
		start.bezocht = false;
		for(Vertex vertex: start.getBuurKnopen()) {
			if(vertex.bezocht) {
				maakAllesWeerNietBezocht(vertex);
			}
		}
	}
	
	class Vertex {
		private ItemType item;
		private Map<Vertex, CostType> neighbours;
		private boolean bezocht;
		private int vroegsteTijd;
		private int laatsteTijd;
		
		public Vertex(ItemType item){
			this.item = item;
			neighbours = new LinkedHashMap<Vertex, CostType>();
		}
		
		public void addZijde(Vertex to, CostType cost) {
			neighbours.put(to, cost);
		}
		
		public ArrayList<Vertex> getBuurKnopen() {
			ArrayList<Vertex> returnVertices = new ArrayList<Vertex>();
			for(Vertex vertex : neighbours.keySet()) {
				returnVertices.add(vertex);
			}
			return returnVertices;
		}
		
		public void setVroegsteTijd(int tijd){
			vroegsteTijd = tijd;
		}
		
		public void setLaatsteTijd(int tijd){
			laatsteTijd = tijd;
		}
		
		public int getVroegsteTijd(){
			return vroegsteTijd;
		}
		
		public int getLaatsteTijd(){
			return laatsteTijd;
		}
		
		public ItemType getItem() {
			return item;
		}
		
		public CostType getCost(Vertex to) {
			return neighbours.get(to);
		}
	}
}
